package com.ifonly.mvc;

import com.ifonly.config.Configuration;
import com.ifonly.config.Constants;
import com.ifonly.core.IfOnly;
import com.ifonly.core.IfOnlyConfig;
import com.ifonly.handler.Handler;
import com.ifonly.logger.Logger;
import com.ifonly.utils.RequestUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * IfOnlyFilter
 *
 *  IfOnly mvc 入口, 用于拦截请求
 *
 * @author <a href="mailto:ifonlymaster@163.com">ifonly</a>
 * @version 1.0 2015-12-09 14:15
 * @since JDK 1.6
 */
public class IfOnlyFilter implements Filter {

    private Logger logger;
    private IfOnly ifOnly = IfOnly.getInstance();
    private String contextPath;
    private int contextPathLen;
    private IfOnlyConfig ifOnlyConfig;
    private String encoding;
    private Handler handler;

    public void init(FilterConfig filterConfig) throws ServletException {
        String configClass = filterConfig.getInitParameter(Constants.CONFIG_CLASS);

        initConfigClass(configClass);

        ServletContext servletContext = filterConfig.getServletContext();

        if (ifOnly.init(servletContext, ifOnlyConfig)) {
            logger = Logger.getLogger(IfOnlyFilter.class);
            handler = ifOnly.getHandler();
            encoding = Configuration.getInstance().getEncoding();
        }

        this.contextPath = servletContext.getContextPath();
        this.contextPathLen = (this.contextPath == null || this.contextPath.equals("/")) ?
                0 : this.contextPath.length();
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);

        String requestURI = request.getRequestURI();
        String actionUrl = RequestUtils.getActionUrl(contextPathLen, requestURI);

        boolean[] isHandled = {false};
        try {
            handler.handle(actionUrl, request, response, isHandled);
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                String qs = request.getQueryString();
                logger.error(qs == null ? actionUrl : actionUrl + "?" + qs, e);
            }
        }

        if (!isHandled[0]) {
            chain.doFilter(req, resp);
        }
    }

    public void destroy() {
        logger.debug("~~~~ ifonly destroy ~~~~");
    }

    private void initConfigClass(String configClass) {
        try {
            Class<?> clazz = Class.forName(configClass);
            Object temp = clazz.newInstance();
            if (temp instanceof IfOnlyConfig) {
                ifOnlyConfig = (IfOnlyConfig) temp;
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Class["+ configClass +"] not found", e);
        } catch (InstantiationException e) {
            throw new RuntimeException("new Class["+ configClass +"] instance failed", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("new Class["+ configClass +"] instance failed", e);
        }
    }


}
